package br.com.it4.zmed.persistence;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

import br.com.it4.framework.persistence.dao.BaseDAOImpl;
import br.com.it4.framework.persistence.exception.PersistenceException;
import br.com.it4.zmed.entity.Medico;
import br.com.it4.zmed.filter.MedicoFilter;

/**
 * Repositório para persistência básica para o medico.
 * 
 * @author Mozart Silva (mozart.vsilva@gmail.com)
 * 
 */
@Repository(value = "medicoRepository")
public class MedicoDAOImpl extends BaseDAOImpl<Medico> implements MedicoDAO {

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    public List<Medico> get(MedicoFilter filtro) throws PersistenceException {
        List<Medico> medicos = null;
        try {
            Query query = this.getQuery(filtro, false);
            medicos = (List<Medico>) query.getResultList();
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
        return medicos;
    }

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    public List<Medico> get(MedicoFilter filtro, int registroInicio, int registroFim) throws PersistenceException {
        List<Medico> medicos = null;
        try {
            Query query = this.getQuery(filtro, false);
            query.setFirstResult(registroInicio);
            query.setMaxResults(registroFim);
            medicos = (List<Medico>) query.getResultList();
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
        return medicos;
    }

    /** {@inheritDoc} */
    public Long getCount(MedicoFilter filtro) throws PersistenceException {
        Long count = null;

        try {
            Query query = this.getQuery(filtro, true);
            count = (Long) query.getSingleResult();
        } catch (Exception e) {
            throw new PersistenceException(e);
        }

        return count;
    }

    /**
     * Monta query de consulta de medico.
     * 
     * @param filtro
     *            Filtro para montagem da query.
     * @param isCount
     *            true se é um count da consulta e false caso seja um consulta
     *            dos dados.
     * @return A Query montada.
     */
    private Query getQuery(MedicoFilter filtro, boolean isCount) {
        EntityManager entityManager = this.getEntityManager();

        StringBuffer jpql = new StringBuffer();
        if (!isCount) {
            jpql.append("select medico from Medico medico ");
        } else {
            jpql.append("select count(medico) from Medico medico ");
        }

        jpql.append("where 1 = 1 ");

        if (filtro.getNome() != null && !filtro.getNome().isEmpty()) {
            jpql.append("and upper(medico.nome) like upper(:nomeMedico) ");
        }

        if (!isCount) {
            jpql.append("order by medico.nome ");
        }

        Query query = entityManager.createQuery(jpql.toString());

        if (filtro.getNome() != null && !filtro.getNome().isEmpty()) {
            query.setParameter("nomeMedico", "%" + filtro.getNome() + "%");
        }

        return query;
    }
}